package com.wwt.server.config.security;

import com.wwt.server.pojo.Menu;
import com.wwt.server.pojo.Role;
import com.wwt.server.service.IMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.util.AntPathMatcher;

import java.util.Collection;
import java.util.List;

/**
 * 权限控制
 * 根据用户的请求URL判断该资源需要什么权限
 * FilterInvocationSecurityMetadataSource 有一个默认的实现类 DefaultFilterInvocationSecurityMetadataSource，
 * 该类的主要功能就是通过当前的请求地址，获取该地址需要的用户角色。
 */
@Configuration
public class CustomFilter implements FilterInvocationSecurityMetadataSource {
    @Autowired
    private IMenuService menuService;
//    @Resource
//    private AntPathMatcher antPathMatcher;
    AntPathMatcher antPathMatcher = new AntPathMatcher();
    @Override
    public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
        FilterInvocation object =(FilterInvocation) o ;
        //获取请求的url
        String requestUrl = object.getRequestUrl();
        //拿到所有角色对应的菜单
        List<Menu> menuByRole = menuService.getMenuByRole();
        for (Menu menu: menuByRole) {
            if (antPathMatcher.match(menu.getUrl(),requestUrl)){
                //把Role集合里的name取出来并转换为一个数组
                String[] roleName = menu.getRole().stream().map(Role::getName).toArray(String[]::new);
                //把当前需要的角色返回  返回的是一个集合 装载的角色信息被访问决定管理器使用
                return SecurityConfig.createList(roleName);
            }
        }
        //不匹配的话就返回默认角色  即登录就可访问的
        return SecurityConfig.createList("ROLE_LOGIN");
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return false;
    }
}
